/**
 * Copyright 2021 Solomon. All rights reserved.
 * Date : 2021.03.24
 */
#include "./inc/spd2010_read_point.h"

struct stTP_SL TP_Sta_Len;
struct stTP_Tocuh Touch;
struct stTP_HDP_STA TP_Hdp_Sta;

/*******************************/
/* Write_TP_Point_Mode_Cmd     */
/*******************************/
void Write_TP_Point_Mode_Cmd(void)
{
    uint8_t sample_data[4];

    sample_data[0] = 0x50;
    sample_data[1] = 0x00;
    sample_data[2] = 0x00;
    sample_data[3] = 0x00;

    I2C_Write(&sample_data[0], sizeof(sample_data));
    nrf_delay_us(200);
}

/*******************************/
/* Write_TP_Start_Cmd          */
/*******************************/
void Write_TP_Start_Cmd(void)
{
    uint8_t sample_data[4];

    sample_data[0] = 0x46;
    sample_data[1] = 0x00;
    sample_data[2] = 0x00;
    sample_data[3] = 0x00;

    I2C_Write(&sample_data[0], sizeof(sample_data));
    nrf_delay_us(200);
}

/*******************************/
/* Write_TP_CPU_Start_Cmd      */
/*******************************/
void Write_TP_CPU_Start_Cmd(void)
{
    uint8_t sample_data[4];

    sample_data[0] = 0x04;
    sample_data[1] = 0x00;
    sample_data[2] = 0x01;
    sample_data[3] = 0x00;

    I2C_Write(&sample_data[0], sizeof(sample_data));
    nrf_delay_us(200);
}

/*******************************/
/* Write_TP_Clear_INT_Cmd      */
/*******************************/
void Write_TP_Clear_INT_Cmd(void)
{
    uint8_t sample_data[4];

    sample_data[0] = 0x02;
    sample_data[1] = 0x00;
    sample_data[2] = 0x01;
    sample_data[3] = 0x00;

    I2C_Write(&sample_data[0], sizeof(sample_data));
    nrf_delay_us(200);
}

/*******************************/
/* Read_TP_Status_Length       */
/*******************************/
uint8_t Read_TP_Status_Length(void)
{
    uint8_t sample_data[4];
    uint8_t w_ret,r_ret;
    sample_data[0] = 0x20;
    sample_data[1] = 0x00;

    w_ret = I2C_Write(&sample_data[0], 2);
    nrf_delay_us(200);
    r_ret = I2C_Read(&sample_data[0], sizeof(sample_data));
    nrf_delay_us(200);
    TP_Sta_Len.Status_L.PT_Exist = (sample_data[0] & 0x01);
    TP_Sta_Len.Status_L.Gesture = (sample_data[0] & 0x02);
    TP_Sta_Len.Status_H.TIC_BUSY = ((sample_data[1] & 0x80) >> 7);
    TP_Sta_Len.Status_H.TIC_IN_BIOS = ((sample_data[1] & 0x40) >> 6);
    TP_Sta_Len.Status_H.TIC_IN_CPU = ((sample_data[1] & 0x20) >> 5);
    TP_Sta_Len.Status_H.TINT_Low = ((sample_data[1] & 0x10) >> 4);
    TP_Sta_Len.Status_H.CPU_RUN = ((sample_data[1] & 0x08) >> 3);
    TP_Sta_Len.Status_L.Aux = ((sample_data[0] & 0x08)); //aux, cytang

    TP_Sta_Len.ReadLen = (sample_data[3] << 8 | sample_data[2]);
    return w_ret && r_ret;
}

/*******************************/
/* Read_TP_HDP                 */
/*******************************/
void Read_TP_HDP(void)
{
    uint8_t sample_data[4+(10*6)]; // 4 Bytes Header + 10 Finger * 6 Bytes
    uint8_t i, offset;
    uint8_t check_id;

    sample_data[0] = 0x00;
    sample_data[1] = 0x03;

    I2C_Write(&sample_data[0], 2);
    nrf_delay_us(200);
    I2C_Read(&sample_data[0], TP_Sta_Len.ReadLen > sizeof(sample_data) ? sizeof(sample_data) : TP_Sta_Len.ReadLen);
    nrf_delay_us(200);

    check_id = sample_data[4];

    if ((check_id <= 0x0A) && TP_Sta_Len.Status_L.PT_Exist)
    {
        Touch.touch_num = ((TP_Sta_Len.ReadLen - 4)/6);
        Touch.gesture = 0x00;

        for (i = 0; i < Touch.touch_num; i++)
        {
            offset = i*6;
            Touch.rpt[i].id = sample_data[4 + offset];
            Touch.rpt[i].x = (((sample_data[7 + offset] & 0xF0) << 4)| sample_data[5 + offset]);
            Touch.rpt[i].y = (((sample_data[7 + offset] & 0x0F) << 8)| sample_data[6 + offset]);
            Touch.rpt[i].weight = sample_data[8 + offset];
        }

        /* For slide gesture recognize */
        if ((Touch.rpt[0].weight != 0) && (Touch.down != 1))
        {
            Touch.down = 1;
            Touch.up = 0 ;
            Touch.down_x = Touch.rpt[0].x;
            Touch.down_y = Touch.rpt[0].y;
        }
        else if ((Touch.rpt[0].weight == 0) && (Touch.down == 1))
        {
            Touch.up = 1;
            Touch.down = 0;
            Touch.up_x = Touch.rpt[0].x;
            Touch.up_y = Touch.rpt[0].y;
        }

        /* Dump Log */
        for (uint8_t finger_num = 0; finger_num < Touch.touch_num; finger_num++)
        {
            NRF_LOG_INFO("ID[%d], X[%d], Y[%d], Weight[%d]\n",
                         Touch.rpt[finger_num].id,
                         Touch.rpt[finger_num].x,
                         Touch.rpt[finger_num].y,
                         Touch.rpt[finger_num].weight);
            NRF_LOG_PROCESS();
        }
    }
    else if ((check_id == 0xF6) && TP_Sta_Len.Status_L.Gesture)
    {
        Touch.touch_num = 0x00;
        Touch.up = 0;
        Touch.down = 0;
        Touch.gesture = sample_data[6] & 0x07;
        NRF_LOG_INFO("Gesture : 0x%02x\n", Touch.gesture);
        NRF_LOG_PROCESS();
    }
    else
    {
        Touch.touch_num = 0x00;
        Touch.gesture = 0x00;
    }
}

/*******************************/
/* Read_TP_HDP_STA             */
/*******************************/
void Read_TP_HDP_STA(void)
{
    uint8_t sample_data[8];

    sample_data[0] = 0xFC;
    sample_data[1] = 0x02;

    I2C_Write(&sample_data[0], 2);
    nrf_delay_us(200);
    I2C_Read(&sample_data[0], sizeof(sample_data));
    nrf_delay_us(200);

    TP_Hdp_Sta.Sta = sample_data[5];
    TP_Hdp_Sta.Next_Packet_Len = (sample_data[2] | sample_data[3] << 8);
}

/*******************************/
/* Read_HDP_REMAIN_DATA        */
/*******************************/
void Read_HDP_REMAIN_DATA(void)
{
    uint8_t sample_data[32];

    sample_data[0] = 0x00;
    sample_data[1] = 0x03;

    I2C_Write(&sample_data[0], 2);
    nrf_delay_us(200);
    I2C_Read(&sample_data[0], TP_Hdp_Sta.Next_Packet_Len > sizeof(sample_data) ? sizeof(sample_data) : TP_Hdp_Sta.Next_Packet_Len);
    nrf_delay_us(200);
}

/*******************************/
/* Read_FW_Version             */
/*******************************/
void Read_FW_Version(void)
{
    uint8_t sample_data[18];
	uint16_t DVer;
	uint32_t Dummy, PID, ICName_H, ICName_L;
    
    memset(sample_data,0,sizeof(sample_data));

    sample_data[0] = 0x26;
    sample_data[1] = 0x00;

    I2C_Write(&sample_data[0], 2);
    nrf_delay_us(200);
    I2C_Read(&sample_data[0], 18);
    nrf_delay_us(200);
	
	Dummy = ((sample_data[0] << 24) | (sample_data[1] << 16) | (sample_data[3] << 8) | (sample_data[0]));
	DVer = ((sample_data[5] << 8) | (sample_data[4]));
	PID = ((sample_data[9] << 24) | (sample_data[8] << 16) | (sample_data[7] << 8) | (sample_data[6]));
	ICName_L = ((sample_data[13] << 24) | (sample_data[12] << 16) | (sample_data[11] << 8) | (sample_data[10]));    // "2010"
	ICName_H = ((sample_data[17] << 24) | (sample_data[16] << 16) | (sample_data[15] << 8) | (sample_data[14]));    // "SPD"

    LOG1("[TP]: Dummy = %#x", Dummy );
    LOG1("[TP]: DVer = %#x", DVer );
    LOG1("[TP]: PID = %#x", PID );
    LOG1("[TP]: ICName_L = %#x", ICName_L );
    LOG1("[TP]: ICName_H = %#x", ICName_H );
}

/*******************************/
/* TP_Read_Data                */
/*******************************/
void TP_Read_Data(void)
{
    static bool passed_bios = false;
    
    if(0 == Read_TP_Status_Length() /*&& passed_bios*/){};
    {
//        #if TPL_FIRMWARE_UPGRADE_SUPPORTED
//        extern void xapp_system_set_tpdfu_mode( void );
//        xapp_system_set_tpdfu_mode();
//        LOG0("[TP]: tpdfu");
//        return;
//        #endif
    }

    if (TP_Sta_Len.Status_H.TIC_IN_BIOS)
    {
        /* Write Clear TINT Command */
        Write_TP_Clear_INT_Cmd();

        /* Write CPU Start Command */
        Write_TP_CPU_Start_Cmd();
        passed_bios = true;
        LOG0("[TP]: in bios");

    }
    else if (TP_Sta_Len.Status_H.TIC_IN_CPU)
    {
        /* Write Touch Change Command */
        Write_TP_Point_Mode_Cmd();

        /* Write Touch Start Command */
        Write_TP_Start_Cmd();

        /* Write Clear TINT Command */
        Write_TP_Clear_INT_Cmd();
        LOG0("[TP]: in cpu");

    }
   else if (TP_Sta_Len.Status_H.CPU_RUN && TP_Sta_Len.ReadLen == 0)
   {
      Write_TP_Clear_INT_Cmd();
      LOG0("[TP]: clr int1");
   }
   else if (TP_Sta_Len.Status_L.PT_Exist
             || TP_Sta_Len.Status_L.Gesture)
    {
        /* Read HDP */
        Read_TP_HDP();
        LOG0("[TP]: in normal");

    HDP_DONE_CHECK:
        /* Read HDP Status */
        Read_TP_HDP_STA();

        if (TP_Hdp_Sta.Sta == 0x82)
        {
            /* Clear INT */
            Write_TP_Clear_INT_Cmd();
        }
        else if (TP_Hdp_Sta.Sta == 0x00)
        {
            /* Read HDP Remain Data */
            Read_HDP_REMAIN_DATA();
            goto HDP_DONE_CHECK;
        }
    }
    else if (TP_Sta_Len.Status_H.CPU_RUN && TP_Sta_Len.Status_L.Aux)
    {
      Write_TP_Clear_INT_Cmd();
      LOG0("[TP]: clr int2");
    }   
    else
    {
      Write_TP_Clear_INT_Cmd();
      LOG0("[TP]: in unknow");
    }
}
